/*!
 * Code block dialog plugin for Editor.md
 *
 * @file        code-block-dialog.js
 * @author      pandao
 * @version     1.2.0
 * @updateTime  2015-03-07
 * {@link       https://github.com/pandao/editor.md}
 * @license     MIT
 */

(function () {
  var factory = function (exports) {
    var cmEditor;
    var pluginName = 'code-block-dialog';

    // for CodeBlock dialog select
    var codeLanguages = (exports.codeLanguages = {
      asp: ['ASP', 'vbscript'],
      actionscript: ['ActionScript(3.0)/Flash/Flex', 'clike'],
      bash: ['Bash/Bat', 'shell'],
      css: ['CSS', 'css'],
      c: ['C', 'clike'],
      cpp: ['C++', 'clike'],
      csharp: ['C#', 'clike'],
      coffeescript: ['CoffeeScript', 'coffeescript'],
      d: ['D', 'd'],
      dart: ['Dart', 'dart'],
      delphi: ['Delphi/Pascal', 'pascal'],
      erlang: ['Erlang', 'erlang'],
      go: ['Golang', 'go'],
      groovy: ['Groovy', 'groovy'],
      html: ['HTML', 'text/html'],
      java: ['Java', 'clike'],
      json: ['JSON', 'text/json'],
      javascript: ['Javascript', 'javascript'],
      lua: ['Lua', 'lua'],
      less: ['LESS', 'css'],
      markdown: ['Markdown', 'gfm'],
      'objective-c': ['Objective-C', 'clike'],
      php: ['PHP', 'php'],
      perl: ['Perl', 'perl'],
      python: ['Python', 'python'],
      r: ['R', 'r'],
      rst: ['reStructedText', 'rst'],
      ruby: ['Ruby', 'ruby'],
      sql: ['SQL', 'sql'],
      sass: ['SASS/SCSS', 'sass'],
      shell: ['Shell', 'shell'],
      scala: ['Scala', 'clike'],
      swift: ['Swift', 'clike'],
      typeScript: ['TypeScript', 'typescript'],
      vb: ['VB/VBScript', 'vb'],
      xml: ['XML', 'text/xml'],
      yaml: ['YAML', 'yaml'],
    });

    exports.fn.codeBlockDialog = function () {
      var _this = this;
      var cm = this.cm;
      var lang = this.lang;
      var editor = this.editor;
      var settings = this.settings;
      var cursor = cm.getCursor();
      var selection = cm.getSelection();
      var classPrefix = this.classPrefix;
      var dialogName = classPrefix + pluginName,
        dialog;
      var dialogLang = lang.dialog.codeBlock;

      cm.focus();

      if (editor.find('.' + dialogName).length > 0) {
        dialog = editor.find('.' + dialogName);
        dialog.find('option:first').attr('selected', 'selected');
        dialog.find('textarea').val(selection);

        this.dialogShowMask(dialog);
        this.dialogLockScreen();
        dialog.show();
      } else {
        var dialogHTML =
          '<div class="' +
          classPrefix +
          'code-toolbar">' +
          dialogLang.selectLabel +
          '<select><option selected="selected" value="">' +
          dialogLang.selectDefaultText +
          '</option></select>' +
          '</div>' +
          '<textarea placeholder="' +
          dialogLang.placeholder +
          '" style="display:none;">' +
          selection +
          '</textarea>';

        dialog = this.createDialog({
          name: dialogName,
          title: dialogLang.title,
          width: 780,
          height: 565,
          mask: settings.dialogShowMask,
          drag: settings.dialogDraggable,
          content: dialogHTML,
          lockScreen: settings.dialogLockScreen,
          maskStyle: {
            opacity: settings.dialogMaskOpacity,
            backgroundColor: settings.dialogMaskBgColor,
          },
          buttons: {
            enter: [
              lang.buttons.enter,
              function () {
                var codeTexts = this.find('textarea').val();
                var langName = this.find('select').val();

                langName = langName === 'other' ? '' : langName;

                cm.replaceSelection(
                  ['```' + langName, codeTexts, '```'].join('\n')
                );

                if (langName === '') {
                  cm.setCursor(cursor.line, cursor.ch + 3);
                }

                this.hide().lockScreen(false).hideMask();

                return false;
              },
            ],
            cancel: [
              lang.buttons.cancel,
              function () {
                this.hide().lockScreen(false).hideMask();

                return false;
              },
            ],
          },
        });
      }

      var langSelect = dialog.find('select');

      if (langSelect.find('option').length === 1) {
        for (var key in codeLanguages) {
          var codeLang = codeLanguages[key];
          langSelect.append(
            '<option value="' +
              key +
              '" mode="' +
              codeLang[1] +
              '">' +
              codeLang[0] +
              '</option>'
          );
        }

        langSelect.append(
          '<option value="other">' + dialogLang.otherLanguage + '</option>'
        );
      }

      var mode = langSelect.find('option:selected').attr('mode');

      var cmConfig = {
        mode: mode ? mode : 'text/html',
        theme: settings.theme,
        tabSize: 4,
        autofocus: true,
        autoCloseTags: true,
        indentUnit: 4,
        lineNumbers: true,
        lineWrapping: true,
        extraKeys: {
          'Ctrl-Q': function (cm) {
            cm.foldCode(cm.getCursor());
          },
        },
        foldGutter: true,
        gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'],
        matchBrackets: true,
        indentWithTabs: true,
        styleActiveLine: true,
        styleSelectedText: true,
        autoCloseBrackets: true,
        showTrailingSpace: true,
        highlightSelectionMatches: true,
      };

      var textarea = dialog.find('textarea');
      var cmObj = dialog.find('.CodeMirror');

      if (dialog.find('.CodeMirror').length < 1) {
        cmEditor = exports.$CodeMirror.fromTextArea(textarea[0], cmConfig);
        cmObj = dialog.find('.CodeMirror');

        cmObj.css({
          float: 'none',
          margin: '8px 0',
          border: '1px solid #ddd',
          fontSize: settings.fontSize,
          width: '100%',
          height: '390px',
        });

        cmEditor.on('change', function (cm) {
          textarea.val(cm.getValue());
        });
      } else {
        cmEditor.setValue(cm.getSelection());
      }

      langSelect.change(function () {
        var _mode = $(this).find('option:selected').attr('mode');
        cmEditor.setOption('mode', _mode);
      });
    };
  };

  // CommonJS/Node.js
  if (
    typeof require === 'function' &&
    typeof exports === 'object' &&
    typeof module === 'object'
  ) {
    module.exports = factory;
  } else if (typeof define === 'function') {
    // AMD/CMD/Sea.js
    if (define.amd) {
      // for Require.js

      define(['editormd'], function (editormd) {
        factory(editormd);
      });
    } else {
      // for Sea.js
      define(function (require) {
        var editormd = require('./../../editormd');
        factory(editormd);
      });
    }
  } else {
    factory(window.editormd);
  }
})();
